<template>
  <BaseModal
    :visible="visibleModal"
    :key="id"
    width="50%"
    :title="`${modalType === 'add' ? '新增' : '更新'}开发任务`"
    @handleCancel="handleCancel"
    @handleOk="handleOk"
  >
    <el-form ref="modelForm" :model="progressData">
      <el-row>
        <el-col>
          <BaseInput
            label="任务标题"
            v-model="progressData.progressName"
            :disabled="modalType === 'edit'"
            prop="progressName"
            :clearable="true"
          >
          </BaseInput>
          <BaseSelect
            label="任务类型"
            v-model="progressData.progressType"
            :disabled="modalType === 'edit'"
            :options="[
              ['1', '前端开发'],
              ['2', '后端开发'],
            ]"
            prop="progressType"
            :clearable="true"
            @change="progressTypeChange"
          >
          </BaseSelect>
          <BaseSelect
            label="处理人"
            v-model="progressData.progressUserId"
            :disabled="[3, 4, 5, 6].includes(progressData.progressStatus)"
            :options="progressUserNames"
            prop="progressUserId"
            noDataText="没有合适的开发者哦、快去添加吧"
            :clearable="true"
          >
          </BaseSelect>
          <BaseSelect
            label="任务优先级"
            v-model="progressData.progressPriority"
            :disabled="[3, 4, 5, 6].includes(progressData.progressStatus)"
            :options="[
              [0, '体验优化'],
              [1, 'bug修复'],
              [2, '进度阻断'],
              [3, '致命垄断'],
            ]"
            prop="progressPriority"
            :clearable="true"
          >
          </BaseSelect>
          <BaseDate
            label="开始时间"
            v-model="progressData.progressCreateBegin"
            :disabled="modalType === 'edit'"
            prop="progressCreateBegin"
            :clearable="true"
          >
          </BaseDate>
          <BaseDate
            label="结束时间"
            v-model="progressData.progressCreateEnd"
            :disabled="[3, 6].includes(progressData.progressStatus)"
            prop="progressCreateEnd"
            :clearable="true"
          >
          </BaseDate>
          <BaseRadioGroup
            v-if="modalType === 'edit'"
            label="任务状态"
            v-model="progressData.progressStatus"
            :option="option"
            @change="radioChange"
          >
          </BaseRadioGroup>
          <BaseProgress
            v-if="modalType === 'edit'"
            label="任务进度"
            v-model="progressData.progressPlan"
            :disabled="[3, 4, 6].includes(progressData.progressStatus)"
            :marksList="[0, 25, 50, 75, 100]"
            @change="progressChange"
          >
          </BaseProgress>
          <div v-if="modalType === 'edit'" style="height: 24px"></div>
          <BaseTextArea
            label="任务描述"
            :minlength="0"
            :maxlength="300"
            :autosize="{ minRows: 3, maxRows: 5 }"
            :showWordLimit="true"
            :disabled="[2, 3, 4, 5, 6].includes(progressData.progressStatus)"
            v-model="progressData.progressContent"
            prop="progressContent"
            :clearable="true"
          >
          </BaseTextArea>
        </el-col>
      </el-row>
    </el-form>
  </BaseModal>
</template>

<script setup lang="ts" name="ProgressModal">
import * as api from "@/api/index";
import {
  BaseInput,
  BaseSelect,
  BaseModal,
  BaseDate,
  BaseTextArea,
  BaseRadioGroup,
  BaseProgress,
} from "@components/BaseForm/index";
import type { FormInstance } from "element-plus";
import { ref, onMounted } from "vue";
import { postAction } from "@api/request";
import { ElMessage as message } from "element-plus";
import { initObj } from "@/uilts/uilts-core";
let emit = defineEmits(["refresh"]);
let props = withDefaults(
  defineProps<{
    modalType: string;
  }>(),
  {
    modalType: "add",
  }
);
// form表单实例
let modelForm = ref<FormInstance>();
// 弹窗状态
let modalType = ref("add");
// 需要提交的数据
let progressData = ref({
  progressName: "", // 任务名称
  progressType: "", // 任务类型
  progressCreateBegin: "", // 任务开始时间
  progressCreateEnd: "", // 任务结束时间
  progressContent: "", // 任务内容
  progressStatus: 1, // 任务状态
  progressPlan: 0, // 任务进度
  progressPriority: null, // 任务优先级
  progressUserId: "", // 处理人ID
});

// 相关API
let pageUrl = {
  add: api.admin.URL_PROGRESSADD,
  edit: api.admin.URL_PROGRESSUPDATE,
};

let progressUserNames: any = ref([]);

let visibleModal = ref(false);

let id = ref("");

let option: any = ref();

let optionFn = (progressStatus: number) => {
  return [
    {
      label: "未开始",
      coreVal: 1,
      desc: "未开始 可以操作任何状态",
      disabled: [2, 3, 4, 5, 6].includes(progressStatus),
    },
    {
      label: "进行中",
      coreVal: 2,
      desc: "已完成 | 已作废 不允许操作 进行中 状态",
      disabled: [3, 5, 6].includes(progressStatus),
    },
    {
      label: "已完成",
      coreVal: 3,
      desc: "已暂停 | 已逾期 | 已作废 不允许操作 已完成 状态",
      disabled: [4, 5, 6].includes(progressStatus),
    },
    {
      label: "已暂停",
      coreVal: 4,
      desc: "已完成 | 已作废 不允许操作 已暂停 状态",
      disabled: [1, 3, 6].includes(progressStatus),
    },
    {
      label: "已逾期",
      coreVal: 5,
      desc: "已作废 不允许操作 已逾期 状态、可修改结束日期将任务变为进行中状态",
      disabled: [1, 3, 4, 6].includes(progressStatus),
    },
    {
      label: "已作废",
      coreVal: 6,
      desc: "已完成任务不允许操作 任何 状态",
      disabled: [3].includes(progressStatus),
    },
  ];
};

/**
 * 处理任务状态变更
 * @param val 必传 任务状态
 */
let radioChange = (val: number) => {
  // 1. 编辑时状态变更为未开始 进度条置0
  if (
    modalType.value === "edit" &&
    val === 1 &&
    progressData.value.progressPlan > 0
  ) {
    let timerId = setInterval(() => {
      progressData.value.progressPlan -= 1;
      // 当进度大于等于100%时 关闭定时器
      if (progressData.value.progressPlan === 0) {
        clearInterval(timerId);
      }
    }, 16);
  }
  // 2. 编辑时状态变更为进行中 进度条为0 则置1
  if (
    modalType.value === "edit" &&
    val === 2 &&
    progressData.value.progressPlan === 0
  ) {
    progressData.value.progressPlan = 1;
  }
  // 3 编辑时当状态变更为已完成且进度未到100%时 开启定时器 自动设为100%
  if (
    modalType.value === "edit" &&
    val === 3 &&
    progressData.value.progressPlan < 100
  ) {
    let timerId = setInterval(() => {
      progressData.value.progressPlan += 1;
      // 当进度大于等于100%时 关闭定时器
      if (progressData.value.progressPlan >= 100) {
        clearInterval(timerId);
      }
    }, 16);
  }
};

let progressChange = (val: any) => {
  // 1. 当进度条大于0时 状态为未开始置为进行中
  if (
    modalType.value === "edit" &&
    val > 0 &&
    progressData.value.progressStatus === 1
  ) {
    progressData.value.progressStatus = 2;
  }
  // 2. 当进度条等于0时 状态改为未开始
  if (
    modalType.value === "edit" &&
    val === 0 &&
    progressData.value.progressStatus !== 1
  ) {
    progressData.value.progressStatus = 1;
  }
  // 3. 当进度条等于100时 状态改为已完成 逻辑有冲突 不使闲该逻辑
  if (
    modalType.value === "edit" &&
    val === 100 &&
    progressData.value.progressStatus !== 3
  ) {
    progressData.value.progressStatus = 3;
  }
};

/**
 * 当类型改变时 重新获取可选操作人
 * @param val 改变的值
 * @param userId 选传 处理编辑时回显问题
 */
let progressTypeChange = (val: string, userId?: string) => {
  // 0 普通用户 1 前端开发 2 后端开发 3 全栈开发
  let userFunc = `3, ${val}`;
  api.admin
    .getUserFunc({ userFunc })
    .then((res: BaseResponse<BaseListType>) => {
      if (res.header.code === 999) {
        // 处理人数据获取成功后清空原数据
        progressUserNames.value.splice(0, progressUserNames.value.length);
        let list = res.body.data;
        list.forEach((item: objectType<any>) => {
          // 重新设置原数据
          progressUserNames.value.push([
            `${item.userId}-${item.userName}-${item.userEmail}-${item.userFuncName}`,
            `${item.userFuncName} - ${item.userName}`,
          ]);
          if (userId && userId === item.userId) {
            // 处理编辑时 处理人回显问题
            progressData.value.progressUserId = `${item.userId}-${item.userName}-${item.userEmail}-${item.userFuncName}`;
          }
        });
      }
    });
};

/**
 * 父组件调用
 * @param val 弹窗开关 true | false 必传
 * @param item 列数据 选传
 */
let handleShow = (val: boolean, item?: objectType<any>) => {
  // 判断第二参数是否存在 存在则是编辑 不然则是新增
  modalType.value = item?.progressId ? "edit" : "add";
  // 第二参数存在是去id属性 供获取详情时使用
  id.value = item?.progressId || "";
  // 打开 | 关闭 弹窗
  visibleModal.value = val;
  // 编辑是调用详情方法 获取详情
  if (modalType.value === "edit") {
    getDetail();
  }
};

let handleCancel = () => {
  // 关闭弹窗
  visibleModal.value = false;
  // 重置表单
  modelForm.value?.resetFields();
  // 初始化数据
  initObj(progressData.value, {
    number: {
      progressStatus: 1,
      progressPlan: 0,
      default: 0,
    },
  });
};

let handleOk = () => {
  // 判断是新增还是编辑吊起对应的接口
  let url = modalType.value === "add" ? pageUrl.add : pageUrl.edit;
  postAction(url, progressData.value).then((res) => {
    if (res.header.code === 999) {
      // 操作成功通知父组件 重新拉取列表数据
      emit("refresh");
      // 关闭弹窗
      handleCancel();
      // 显示通知用户
      message.success(
        res.header.message ||
          (modalType.value === "add" ? "新增成功" : "更新成功")
      );
      return;
    }
  });
};

// 获取详情
let getDetail = () => {
  if (id.value) {
    // id存在则通过接口获取详情数据
    api.admin.progressDetail({ progressId: id.value }).then((res) => {
      if (res.header.code === 999) {
        // 请求成功后赋值 调用fixednessOrigin 直接赋值会失去响应式 因为不是同一个对象
        fixednessOrigin(progressData.value, { ...res.body });
        // 重设任务状态选项
        option.value = optionFn(progressData.value.progressStatus);
        // 重设类型选项
        progressTypeChange(
          progressData.value.progressType,
          progressData.value.progressUserId
        );
      }
    });
  }
};

/**
 * 源对象属性赋值 不改变源对象
 * @param originObj 源对象 必传
 * @param dataObj 属性对象 必传
 */
let fixednessOrigin = (
  originObj: objectType<any>,
  dataObj: objectType<any>
) => {
  let dataArr = Object.entries(dataObj);
  dataArr.forEach((item) => {
    originObj[item[0]] = item[1];
  });
};

// 暴露给父组件调用
defineExpose({
  handleShow,
});
</script>

<style lang="less" scoped></style>
